const ffmpeg = require("fluent-ffmpeg")
const path = require("path")
const fs = require("fs")

// 输入输出路径设置
const filename = "input1.mp4"
const inputPath = path.resolve(__dirname, filename)
const outputDir = path.resolve(
  __dirname,
  "../public/adaptive",
  filename.replace(path.extname(filename), "")
)

/**
 * 生成FFmpeg的多码率HLS输出选项
 * @param {string} inputFile - 输入文件路径
 * @param {string} outputBaseDir - 输出基础目录
 * @param {Array<Object>} videoConfigs - 视频配置数组，每个对象包含 width, height, bitrate, profile
 * @param {Object} audioConfig - 音频配置 {bitrate, channels}
 * @param {Object} hlsConfig - HLS配置 {segmentTime, segmentSize, segmentType}
 * @returns {Object} 包含outputOptions和outputFiles的数组，每个视频配置一个对象
 */
function generateAdaptiveHLSOptions(
  inputFile,
  outputBaseDir,
  videoConfigs,
  audioConfig,
  hlsConfig
) {
  console.log(`开始生成多码率HLS转换选项...`)

  // 检查输入文件
  if (!fs.existsSync(inputFile)) {
    throw new Error(`输入文件不存在: ${inputFile}`)
  }

  // 创建输出基础目录
  if (!fs.existsSync(outputBaseDir)) {
    fs.mkdirSync(outputBaseDir, { recursive: true })
  }

  // 为每个视频质量创建目录和配置
  const streamConfigs = videoConfigs.map((config, index) => {
    // 使用分辨率创建目录名
    const dirName = `stream_${config.width}_${config.height}`
    const streamDir = path.join(outputBaseDir, dirName)

    if (!fs.existsSync(streamDir)) {
      fs.mkdirSync(streamDir, { recursive: true })
    }

    // 为每个流构建输出选项
    const outputOptions = [
      // 选择视频和音频流
      "-map 0:v:0",
      "-map 0:a:0",

      // 视频设置
      `-b:v ${config.bitrate}k`,
      `-c:v libx264`,
      `-s:v ${config.width}x${config.height}`,
      `-profile:v ${config.profile || "main"}`,

      // 音频设置
      "-c:a aac",
      `-b:a ${audioConfig.bitrate || 128}k`,
      `-ac ${audioConfig.channels || 2}`,

      // HLS 设置
      "-f hls",
      `-hls_time ${hlsConfig.segmentTime || 30}`,
      `-hls_list_size ${hlsConfig.segmentSize || 0}`,
      `-hls_segment_type ${hlsConfig.segmentType || "mpegts"}`,
      "-hls_flags independent_segments",
      `-hls_segment_filename ${path.join(streamDir, "segment_%03d.ts")}`
    ]

    return {
      config,
      dirName,
      outputOptions,
      outputFile: path.join(streamDir, "playlist.m3u8")
    }
  })

  // 返回所有流配置
  return streamConfigs
}

/**
 * 创建主播放列表文件
 * @param {string} outputBaseDir - 输出基础目录
 * @param {Array<Object>} videoConfigs - 视频配置数组
 */
function createMasterPlaylist(outputBaseDir, videoConfigs) {
  const masterPlaylistPath = path.join(outputBaseDir, "master.m3u8")
  console.log(`创建主播放列表: ${masterPlaylistPath}`)

  // 创建主播放列表内容
  let masterContent = `#EXTM3U\n#EXT-X-VERSION:3\n\n`

  // 为每个视频质量添加一个流条目
  videoConfigs.forEach((config, index) => {
    const bandwidth = config.bitrate * 1000 + 128000 // 视频码率 + 音频码率
    const dirName = `stream_${config.width}_${config.height}`

    masterContent += `#EXT-X-STREAM-INF:BANDWIDTH=${bandwidth},RESOLUTION=${config.width}x${
      config.height
    },CODECS="avc1.${config.profile === "baseline" ? "42c00d" : "4d401f"},mp4a.40.2"\n`
    masterContent += `${dirName}/playlist.m3u8\n`
  })

  // 写入主播放列表文件
  fs.writeFileSync(masterPlaylistPath, masterContent)
  console.log("主播放列表已创建")
}

async function createAdaptivePlaylist(outputBaseDir, config, streamDir) {
  const adaptivePlaylistPath = path.join(outputBaseDir, streamDir, "index.m3u8")
  console.log(`创建适配播放列表: ${adaptivePlaylistPath}`)

  let adaptiveContent = `#EXTM3U\n#EXT-X-VERSION:3\n\n`
  const bandwidth = config.bitrate * 1000 + 128000 // 视频码率 + 音频码率
  adaptiveContent += `#EXT-X-STREAM-INF:BANDWIDTH=${bandwidth},RESOLUTION=${config.width}x${
    config.height
  },CODECS="avc1.${config.profile === "baseline" ? "42c00d" : "4d401f"},mp4a.40.2"\n`
  adaptiveContent += `playlist.m3u8\n`

  fs.writeFileSync(adaptivePlaylistPath, adaptiveContent)
  console.log("适配播放列表已创建")
}

async function convertToAdaptiveHLS() {
  console.log("开始多码率HLS转换示例...")

  // 视频质量配置，从低到高
  const videoConfigs = [
    { width: 640, height: 360, bitrate: 500, profile: "baseline" }, // 低质量
    { width: 854, height: 480, bitrate: 1000, profile: "main" }, // 中质量
    { width: 1280, height: 720, bitrate: 3200, profile: "high" } // 高质量
    // { width: 1920, height: 1080, bitrate: 3200, profile: "high" } // 高质量
  ]

  // 音频和HLS配置
  const audioConfig = { bitrate: 128, channels: 2 }
  const hlsConfig = { segmentTime: 10, segmentSize: 0, segmentType: "mpegts" }

  try {
    // 生成每个质量级别的配置
    const streamConfigs = generateAdaptiveHLSOptions(
      inputPath, // 输入文件
      outputDir, // 输出目录
      videoConfigs, // 视频配置
      audioConfig, // 音频配置
      hlsConfig // HLS配置
    )

    // 为每个质量级别执行一个FFmpeg命令
    for (const config of streamConfigs) {
      await new Promise((resolve, reject) => {
        console.log(`开始处理 ${config.dirName}...`)

        ffmpeg(inputPath)
          .videoCodec("libx264")
          .audioCodec("aac")
          .outputOptions(config.outputOptions)
          .output(config.outputFile)
          .on("start", commandLine => {
            console.log(`FFmpeg命令 (${config.dirName}):`, commandLine)
          })
          .on("progress", progress => {
            if (progress.percent) {
              console.log(`处理进度： (${config.dirName}): ${Math.round(progress.percent)}% `)
            }
          })
          .on("stderr", stderrLine => {
            // console.log(`FFmpeg输出 (${config.dirName}):`, stderrLine)
          })
          .on("end", async () => {
            console.log(`${config.dirName} 转换完成!`)
            await createAdaptivePlaylist(outputDir, config.config, config.dirName)
            resolve()
          })
          .on("error", err => {
            console.error(`${config.dirName} 转换失败:`, err.message)
            reject(err)
          })
          .run()
      })
    }

    // 所有视频处理完成后，创建主播放列表
    createMasterPlaylist(outputDir, videoConfigs)
    console.log("多码率 HLS 转换全部完成!")
  } catch (error) {
    console.error("转换过程中出错:", error)
  }
}

// 开始转换
convertToAdaptiveHLS()
